﻿Shader "Lch/SkyFast"
{
    Properties
    {
        _SkyColor ("天空颜色",Color) = (0.2111516, 0.4499154, 0.6886792,1)
        _MinColor ("米氏颜色",Color) = (1, 1, 1,1) 
        _MinCtrl("米氏控制",Range(1,20))=8
		_MinHeight("米氏起始高度",Range(-0.3,0.3)) = 0
        [HDR]_SunColor("太阳色",Color)=(1., 1., 0.4,1.0)
        _SunSize ("Sun Size", Range(0.99, 0.999)) = 0.999
		_SunEdge("Sun Edge",Range(0.0001,0.01)) = 0.001
	    [HDR]_SunRayColor("太阳辉光色",Color)=(0.5, 0.3695906, 0.1533019,1.0)
        _SunRayCtrl("辉光范围",Range(2,255)) = 20

		_ColorColorSun("云层色",Color) = (1,1,1,1)
		_ColorColor("云层色",Color) = (1,1,1,1)
        _CloudRayColor("云辉光色",Color)=(1., 0.7, 0.2,1.0)

        
        

        _CloudTexture ("Cloud Texture", 2D) = "white" {}
        

	    _CloudSteps ("Cloud Steps", Range(5, 10)) = 10
        _CloudMarchDist ("Cloud March Distance", Range(0.1, 1)) = 0.187
	 

	    _CloudIntensity("_CloudIntensity",Range(0,100)) = 100
        _CloudAmbient ("Cloud Ambient", Range(0, 20)) = 10
	    _CloudArea("_CloudArea",Range(0,1)) = 0.5
        _RotationSpeed("_RotationSpeed",Range(0,0.03)) = 0.01

	    _CloudNoise ("_CloudNoise", 2D) = "black" {}


		_A("_A 控制对比度",Range(0,4)) = 2.51
		/*_B("_B 调整亮度",Range(0,3)) = 0.03
		_C("_C 控制对比度",Range(0,3)) = 2.43
		_D("_D 控制高光",Range(0,3)) = 0.59*/
		_E("_E 控制低光",Range(0,3)) = 0.14

     

 
		 

        [Toggle(_CUSTOM_LIGHT_ANGLE)]_CUSTOM_LIGHT_ANGLE("自定义光源角度",int) = 0
		_SunAngle("太阳角度",Range(-10,60) ) = 30
	      [Enum(LEqual, 4, Always, 8 )]
        _ZTest ("深度测试", Float) = 4

		_FogStar("雾开始", Range(1,1000)) = 500

		_FogThickness("雾厚度", Range(1,1000)) = 100


    }
    SubShader
    {
        Tags {   "RenderPipeline" = "UniversalPipeline"  "Queue"="Background" "RenderType"="Background" "PreviewType"="Skybox" }

        Cull Off ZWrite Off 
		Blend SrcAlpha OneMinusSrcAlpha // Traditional transparency
        Pass
        {
            ZTest [_ZTest]
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #pragma multi_compile   _ SKY_FOG_EFFECT
			#pragma multi_compile _ _CUSTOM_LIGHT_ANGLE

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
		    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
		    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"


            #define UNITY_PI 3.1415926
		    CBUFFER_START(UnityPerMaterial)
      
            float4 _SunColor;
            float _SunSize;
			float _SunEdge;
            float4 _SunRayColor;
            float4 _SkyColor;
            float4 _MinColor;
            float _MinCtrl;
			float _MinHeight;
            float  _SunRayCtrl;

            float _SunAngle;
            float _CloudSteps;
			float _CloudMarchDist;
			float _CloudAmbient;
			float  _CloudIntensity;
			float _CloudArea;
			float _RotationSpeed;
			float _TestCloud;
			float _CloudDisOffet;
			float _CloudAOPower;
            float4 _CloudRayColor;


            float _FogStar;
			float _FogThickness;
			 
			float _ShowScene;
 
			float4 _ColorColorSun;
			float4 _ColorColor;
 

			float _A;
			/*float _B;
			float _C;
			float _D;*/
			float _E;
            CBUFFER_END


         
		    // 云层相关属性
             sampler2D _CloudTexture;
		    sampler2D _CloudNoise;
         
            struct Attributes
            {
                float4 positionOS   : POSITION;
            };

            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
                float3 texcoord : TEXCOORD0;
                float4 ScreenPosition : TEXCOORD1; 

				 #if _CUSTOM_LIGHT_ANGLE
				 float3 sunDir : TEXCOORD2; 

				 #endif

            };
            float3 RotateAroundAxis(float3 dir,float3 axis,float angle)
			{
				axis = normalize(axis);

 
				float cosAngle = cos(angle);
				float sinAngle = sin(angle);
				float oneMinusCos = 1 - cosAngle;

 
				float xx = axis.x * axis.x;
				float xy = axis.x * axis.y;
				float xz = axis.x * axis.z;
				float yy = axis.y * axis.y;
				float yz = axis.y * axis.z;
				float zz = axis.z * axis.z;

 
				float3x3 rotationMatrix = float3x3(
					cosAngle + xx * oneMinusCos,
					xy * oneMinusCos - axis.z * sinAngle,
					xz * oneMinusCos + axis.y * sinAngle,

					xy * oneMinusCos + axis.z * sinAngle,
					cosAngle + yy * oneMinusCos,
					yz * oneMinusCos - axis.x * sinAngle,

					xz * oneMinusCos - axis.y * sinAngle,
					yz * oneMinusCos + axis.x * sinAngle,
					cosAngle + zz * oneMinusCos
				);

 
				return mul(rotationMatrix, dir);
			}

            Varyings vert(Attributes i)
            {

                Varyings o;
                o.positionHCS = TransformObjectToHClip(i.positionOS.xyz);
                o.texcoord = i.positionOS.xyz;

                o.ScreenPosition = ComputeScreenPos(o.positionHCS );

				#if _CUSTOM_LIGHT_ANGLE
				Light light = GetMainLight( );
				float3 dir0 = light.direction;
				float3 dir1 = normalize( float3(dir0.x,0,dir0.z));
				float3 dir3 = -cross(half3(0,1,0),dir1);
			    o.sunDir = RotateAroundAxis(dir1,dir3,_SunAngle*UNITY_PI/180.0);
				#endif

                return o;
            }
            static float3 lgt = normalize(float3(0., 0.27, -0.9));
            /*uniform float A  ;  // 控制对比度
		    uniform	float B  ;  // 调整亮度
		    uniform	float C  ;  // 控制对比度
		    uniform	float D  ;  // 控制高光
		    uniform	float E  ;  // 控制低光*/
		    float3 tonemapACES(float3 color)
		    {
			    //float A = 2.51;  // 控制对比度
			    float B = 0.03;  // 调整亮度
			    float C = 2.43;  // 控制对比度
			    float D = 0.59;  // 控制高光
			    //float E = 0.14;  // 控制低光*/

				float A = _A;  // 控制对比度
			    //float B = _B;  // 调整亮度
			    //float C = _C;  // 控制对比度
			    //float D = _D;  // 控制高光
			    float E = _E;  // 控制低光*/

			    // 使用 ACES 映射公式
			    return saturate((color * (A * color + B)) / (color * (C * color + D) + E));
		    }
            float3 RotateAroundY (float3 vertex, float alpha)
            {
           
                float sina, cosa;
                sincos(alpha, sina, cosa);
                float2x2 m = float2x2(cosa, -sina, sina, cosa);
                return float3(mul(m, vertex.xz), vertex.y).xzy;
            }
            float3 RotateAroundYInDegrees (float3 vertex, float degrees)
            {
                float alpha = degrees * UNITY_PI / 180.0;
                float sina, cosa;
                sincos(alpha, sina, cosa);
                float2x2 m = float2x2(cosa, -sina, sina, cosa);
                return float3(mul(m, vertex.xz), vertex.y).xzy;
            }
            float2 DirToMatCapUV(float3 dir, float yScale)
		    {
			    if(_TestCloud>0)
			    {
				    dir = RotateAroundY(dir,_TestCloud);
			    }
			    else
			    {
				    dir = RotateAroundY(dir,_Time.y*_RotationSpeed);
			    }
			
				      // 保证输入是单位向量
			    dir.y *= yScale;              // 压缩 Y 分量，增强平视区域密度

			    dir = normalize(dir);   
			    float2 uv = dir.xz  ;
			    return uv * 0.5 + 0.5;
		    }

		float3 MatCapUVToDir(float2 uv, float yScale)
		{
			float3 dir;
			dir.xz  = uv.xy * 2 - 1;
			// 计算dir.xz自身的点积
			float dotResult = dot(dir.xz, dir.xz);
			// 确保1.0 - dotResult是非负的
			dir.y = sqrt(max(0.0, 1.0 - dotResult));
			dir.y/=yScale;
		   return normalize( dir) ;
		}
        float clouds(float2 uv)
		{
		return tex2D (_CloudTexture, uv).r;
		}
         void getClouds2D(in float3 ro, in float3 rd, float scnD, float3 sun, float3 skyCol,inout float3 col)
		 {
			
			
			if(rd.y>0)
			{

				 
 
				float noise = tex2D(_CloudNoise,float2(rd.x,rd.z  )*10.0 -_Time.y*0.05);
				float2 uv = DirToMatCapUV(rd,1.6);

				uv+=noise*0.006;
				float2 m = DirToMatCapUV(lgt,1.6);

				 float cloudShape = clouds(uv );
			 
				float2 marchDist = _CloudMarchDist ;

				 float stepsInv = 1./_CloudSteps;
				float aoPower = _CloudAmbient/_CloudSteps;
				float2 sunDir = normalize(m-uv)*marchDist*stepsInv;
			 
 
				float cloudColor = 1.;
				float2 marchUv = uv;

 
				//_CloudNoise
				UNITY_LOOP
				for (float i = 0.;i<marchDist.x; i += marchDist.x*stepsInv)
				{
					marchUv += sunDir*i;
					float c = clouds(marchUv );
					cloudColor *= clamp(1.-c*aoPower, 0., 1.);
				} 
 
                cloudColor = exp(-cloudColor)*(1.-exp(-cloudColor*2.))*2.;
				float colt = cloudColor;
                cloudColor *= cloudShape;
				float lDotV = dot(lgt,rd);
				float t2 = smoothstep(_CloudArea,1,lDotV);

				//skyCol = lerp(skyCol,_SunColor.rgb,sun * smoothstep(0., 0.4, cloudShape) );
			 
				

                col = skyCol+  lerp(_ColorColor.rgb,_ColorColorSun.rgb,t2)*cloudShape;
                
				col =lerp( col,_SunColor, (1.-smoothstep(0., 0.4, cloudShape))* sun) ;
	 
                float3 cloudCol = _CloudRayColor.rgb*_CloudIntensity * cloudColor  ;
                col = lerp(col,cloudCol , cloudShape*t2);
             

				
           
                
  
			}
 
			
		 }
            


             

            float3 getSun(float3 rd, float sunCoeff)
		    {
			    float rdl = max(dot(rd, lgt), 0.);
 
	 
			    float3 sun = smoothstep(_SunSize ,_SunSize+_SunEdge , rdl) ; 
			 
			    return sun;
		    }
            float3 render(  in float3 ro, in float3 rd , out float3 bg )
            {
                float3 col;
                col = _SkyColor.rgb ;
                float rdl = dot(rd, lgt) ;
                float sunDot = max(rdl,0);
                 
                //米氏
                col = lerp(col, _MinColor.rgb, pow(1.-max( rd.y+_MinHeight , 0.), _MinCtrl));

                float3 sun =  getSun(rd,  0.6   ) ;
                
               
				 
                
                float rdl1 = dot(float3(rd.x,abs(rd.y),rd.z), lgt) ;
               
               
                col += _SunRayColor.rgb*pow(max(rdl1,0), _SunRayCtrl); 
                bg = col;

               
                

                getClouds2D(ro, rd, 10000., sun,  bg,col);

               
                return col;
            }
            half4 frag(Varyings i) : SV_Target
            {
                float3 ro = 0;
                float3 ray = normalize( i.texcoord);
                Light light = GetMainLight( );

                 
				 lgt = light.direction;
               

                #if _CUSTOM_LIGHT_ANGLE
				lgt = i.sunDir ;
			#else
				lgt = light.direction; 
			#endif

				float3 bg;
                float3 atm = render( 0,ray,bg);
                float4 fragColor =  float4(atm   , 1.);

                //fragColor.rgb = tonemapACES(fragColor.rgb);
				
           

			#if SKY_FOG_EFFECT
			 
			 
            
			float2 screenPos = i.ScreenPosition.xy / i.ScreenPosition.w;
			float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, screenPos);
			 
			depth = LinearEyeDepth(depth, _ZBufferParams) ;
			
		 
			if (depth <  _ProjectionParams.z  *0.95  ) { 
				
                float fogFactor = clamp( ( depth-_FogStar )/_FogThickness ,0,1 );
		 
				return float4(tonemapACES(bg.rgb),fogFactor);
            }
			
		    
			#endif
				fragColor.rgb =  tonemapACES(fragColor.rgb)  ;
                return fragColor;

                
               
            }
            ENDHLSL
        }
    }
}